package com.pansoft.openplanet.activity;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextWatcher;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.efounder.chat.activity.BaseActivity;
import com.efounder.constant.EnvironmentVariable;
import com.efounder.utils.ResStringUtil;
import com.pansoft.openplanet.R;
import com.pansoft.openplanet.bean.Account;
import com.pansoft.openplanet.bean.EscrowAccountListBean;
import com.pansoft.openplanet.bean.WalletBean;
import com.pansoft.openplanet.constant.IPAssetsConstant;
import com.pansoft.openplanet.db.AccountDao;
import com.pansoft.openplanet.fragment.BottomWalletChooseDialogFragment;
import com.pansoft.openplanet.util.DecimalDigitsInputFilter;
import com.pansoft.openplanet.util.EosNetParamUtil;
import com.pansoft.openplanet.util.EthTokenTransactionManager;
import com.pansoft.openplanet.util.TCMathUtil;
import com.pansoft.openplanet.util.TCRequestUtil;
import com.pansoft.openplanet.util.TCStringUtil;
import com.pansoft.openplanet.widget.PassWordAlertDialog;
import com.pansoft.openplanet.widget.TCLoadingDataView;
import com.utilcode.util.LogUtils;
import com.utilcode.util.ToastUtils;

import net.sf.json.JSONObject;

import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.tx.Contract;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static androidx.fragment.app.DialogFragment.STYLE_NO_FRAME;

/**
 * 托管账户提现
 *
 * @author will
 */
public class WithdrawActivity extends BaseActivity implements View.OnClickListener {

    public static final String TAG = "WithdrawActivity";
    private TextView tvBlockChainMoney;//可用托管余额
    private EditText etQuantity;//提现数量
    private TextView etTxFee;//提现手续费
    private TextView tvInsufficientBalance;//手续费不足提示
    private Button btnWithdraw;//提现按钮

    private LinearLayout llAddress;
    private TextView tvWallet;//钱包名称
    private TextView tvPay;//付款地址
    private TextView tvAll;//全部提现


    private EscrowAccountListBean.AssetsBean assetsBean;
    private List<WalletBean> walletBeans = new ArrayList<>();
    private int ipaChainId = IPAssetsConstant.CHAIN_ID_ETH;
    private String curAddress;
    private Account curAccount;
    private AccountDao accountDao;
    private EthTokenTransactionManager transactionManager;

    private double escrowBalance = 0.0000;//托管余额
    private double withdrawFee = 0.002;//提现手续费
    private double withdrawQuantity = 0.00;//提现数量
    private double curAccountBalance = 0.00;// 当前账户余额，用于支付手续费
    private String gas = "0.0004";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.open_planet_activity_withdraw);
        accountDao = new AccountDao(this);
        initView();
        initData();
    }

    public static void start(Context context, EscrowAccountListBean.AssetsBean assetsBean) {
        Intent starter = new Intent(context, WithdrawActivity.class);
        starter.putExtra("assetsBean", assetsBean);
        context.startActivity(starter);
    }

    private void initView() {
        TextView tvTitle = (TextView) findViewById(R.id.tv_title);
        tvTitle.setText(ResStringUtil.getString(R.string.open_planet_withdraw));

        tvBlockChainMoney = (TextView) findViewById(R.id.tv_block_chain_money);
        etQuantity = (EditText) findViewById(R.id.et_quantity);
        etTxFee = (TextView) findViewById(R.id.et_tx_fee);
        tvInsufficientBalance = (TextView) findViewById(R.id.tv_insufficient_balance);
        btnWithdraw = (Button) findViewById(R.id.tv_create_wallet);
        btnWithdraw.setOnClickListener(this);
        tvAll = (TextView) findViewById(R.id.tv_all);
        tvAll.setOnClickListener(this);
        llAddress = (LinearLayout) findViewById(R.id.ll_address);
        llAddress.setOnClickListener(this);
        tvWallet = (TextView) findViewById(R.id.tv_wallet);
        tvPay = (TextView) findViewById(R.id.tv_pay);

        etQuantity.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(8)});
        etQuantity.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(Editable editable) {
                if (etQuantity.hasFocus()) {//本editText获取焦点
                    if (!editable.toString().equals("") || editable.toString().startsWith(".")) {//输入不为""
                        if (!TCStringUtil.inputIsNumber(editable.toString())) {
                            ToastUtils.showShort(R.string.open_planet_amount_not_correct);
                            etQuantity.setText("");
                        } else {
                            String quantity = etQuantity.getText().toString();
                            if (quantity.startsWith(".")) {
                                quantity = "0".concat(quantity);
                                etQuantity.setText(quantity);
                                etQuantity.setSelection(etQuantity.getText().length());
                            }
                            withdrawQuantity = Double.valueOf(quantity);
                        }
                    }
                }

            }
        });
    }

    private void initData() {
        assetsBean = (EscrowAccountListBean.AssetsBean) getIntent().getSerializableExtra("assetsBean");
        //余额，手续费
        escrowBalance = assetsBean.getAvailableCoin();
        tvBlockChainMoney.setText(TCMathUtil.retainAsignDecimals(escrowBalance, 8) + assetsBean.getCoinName());
        etTxFee.setText(withdrawFee + assetsBean.getCoinName());

        ipaChainId = Integer.valueOf(assetsBean.getBlockchainId());
        if (ipaChainId == IPAssetsConstant.CHAIN_ID_ETH) {
            initLocalWalletData(IPAssetsConstant.ChainEnum.ETH);
        } else if (ipaChainId == IPAssetsConstant.CHAIN_ID_BTC) {
            initLocalWalletData(IPAssetsConstant.ChainEnum.BTC);
        } else if (ipaChainId == EosNetParamUtil.getEosChainId()) {
            initLocalWalletData(EosNetParamUtil.getEosChainEnum());

        } else if (ipaChainId == IPAssetsConstant.CHAIN_ID_TURBOCHAIN) {
            curAccount = accountDao.getMainAccount();
            curAddress = curAccount.getAddress();
            if (curAccount != null) {
                WalletBean walletBean = new WalletBean.Builder()
                        .accountName(curAccount.getAcccountName())
                        .avatar(curAccount.getAccountAvatar())
                        .address(curAccount.getAddress())
                        .balance("0")
                        .isSelected(true)
                        .build();
                walletBeans.add(walletBean);
            }
            setPayData();
            requestAccountBalance();
        }
        if (ipaChainId == IPAssetsConstant.CHAIN_ID_BTC || ipaChainId == EosNetParamUtil.getEosChainId()) {
//            llExpense.setVisibility(View.INVISIBLE);
        }
    }

    /* 初始化本地钱包数据，根据intent里的类型，决定是哪一类账户
     * @param blockChainEnum ETH，BTC等
     */
    private void initLocalWalletData(IPAssetsConstant.ChainEnum blockChainEnum) {
        List<Account> accountList;
        if (ipaChainId == EosNetParamUtil.getEosChainId()) {
            accountList = accountDao.getAllActivatedEosAccount(blockChainEnum);
        } else {
            accountList = accountDao.getAllChildAccount(blockChainEnum);
        }
        if (accountList != null) {
            for (int i = 0; i < accountList.size(); i++) {
                Account account = accountList.get(i);
                if (account.getAccountType() == Account.ACCOUNT_TYPE_OBSERVE) {
                    //观察钱包不能转账
                    continue;
                }
                WalletBean walletBean = new WalletBean.Builder()
                        .accountName(account.getAcccountName())
                        .avatar(account.getAccountAvatar())
                        .address(account.getAddress())
                        .balance("0")
                        .build();

                walletBeans.add(walletBean);

            }
            if (accountList.size() > 0) {
                curAccount = accountList.get(0);
                curAddress = curAccount.getAddress();
                setPayData();
                requestAccountBalance();
            }
        }
    }

    /**
     * 开始提现，发送交易费
     */
    private void sendWithdrawFee() {
        TCLoadingDataView.show(this, ResStringUtil.getString(R.string.open_planet_withdrawing));
        transactionManager = new EthTokenTransactionManager(this);
        Account account = accountDao.getAccount(curAddress);
        if (account != null){
            transactionManager.loadCredentialsASync(account,
                    new EthTokenTransactionManager.LoadCredentialsCallBack() {
                        @Override
                        public void loadResult(boolean isSuccess, final Credentials credentials) {
                            if (!isSuccess) {
//                                ToastUtil.showToast(AppContext.getInstance(), "提现失败");
                                showAlertDailog(ResStringUtil.getString(R.string.open_planet_withdraw_fail), false);
                                TCLoadingDataView.dismiss();
                                return;
                            }
                            //2.获取nonce
//                            LogUtils.i("获取nonce", credentials.getAddress());
                            transactionManager.getTransactionNonce(curAddress,ipaChainId, new EthTokenTransactionManager.NonceCallBack() {
                                @Override
                                public void nonceResult(boolean isSuccess, BigInteger nonce) {
                                    if (!isSuccess) {
//                                        ToastUtil.showToast(AppContext.getInstance(), "提现失败");
                                        showAlertDailog(ResStringUtil.getString(R.string.open_planet_withdraw_fail), false);
                                        TCLoadingDataView.dismiss();
                                        return;
                                    }
                                    //3.开始转账
//                                    LogUtils.i("开始转账", nonce);
                                    //普通转账
                                    BigInteger gasPrice = Convert.toWei(String.valueOf(withdrawFee), Convert.Unit.ETHER).toBigInteger().divide(Contract.GAS_LIMIT);

                                    ethTransaction(nonce, credentials);
                                }
                            });
                        }
                    });
        }
    }

    /**
     * 非智能合约转账
     *
     * @param nonce
     * @param credentials
     */
    public void ethTransaction(BigInteger nonce, Credentials credentials) {

        String hexValue = null;
        try {
            //创建交易
            RawTransaction rawTransaction = RawTransaction.createEtherTransaction(nonce,
                    Convert.toWei(gas, Convert.Unit.ETHER).toBigInteger().divide(Contract.GAS_LIMIT),
                    Contract.GAS_LIMIT, assetsBean.getSysAddress(), Convert.toWei(String.valueOf(withdrawFee), Convert.Unit.ETHER).toBigInteger());
            //签名Transaction，这里要对交易做签名
            byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
            hexValue = Numeric.toHexString(signedMessage);
//            LogUtils.i("交易签名：" + hexValue);
        } catch (Exception e) {
            e.printStackTrace();
//            ToastUtil.showToast(AppContext.getInstance(), "提现失败");
            showAlertDailog(ResStringUtil.getString(R.string.open_planet_withdraw_fail), false);
            TCLoadingDataView.dismiss();
            return;
        }
        rechargeMoneyToServer(hexValue, String.valueOf(withdrawQuantity), curAddress);
    }

    public void rechargeMoneyToServer(String signedTransactionData, String value, String txTo) {
        HashMap<String, String> map = new HashMap<>();
        map.put("userId", EnvironmentVariable.getUserName());
        map.put("trusteeshipCoinId", assetsBean.getTrusteeshipId() + "");
        map.put("signedTransactionData", signedTransactionData);
        map.put("value", value);
        map.put("txTo", txTo);

//        >userId    用户编号(String)
//                >trusteeshipId 托管币编号(Integer)
//                >signedTransactionData 交易签名数据(String)
//                >value 交易额(double)
//>from 转出托管账户地址(String) 手机号
//                >txFrom 转出地址(String)
//                >txTo 转入地址(String)
        TCRequestUtil.getCommonRequest(TAG, "trusteeship/reflect", map, new TCRequestUtil.TCRequestCallback() {
            @Override
            public void onSuccess(String response) {
                TCLoadingDataView.dismiss();
                LogUtils.i(response + "");
                // {"result":"success","transactionHash":"0x5c5ee42ba360fa772b21690ef95a6532b83c12e662e2f999f3377cad9dbe8628"}
                try {
                    org.json.JSONObject jsonObject = new org.json.JSONObject(response);
                    if (jsonObject.optString("result", "").equals("success")) {
                        showAlertDailog(ResStringUtil.getString(R.string.open_planet_withdraw_success), true);
                    } else {
                        showAlertDailog(ResStringUtil.getString(R.string.open_planet_withdraw_fail), false);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                    showAlertDailog(ResStringUtil.getString(R.string.open_planet_withdraw_fail), false);
//                    ToastUtil.showToast(AppContext.getInstance(), "提现失败");
                }

            }

            @Override
            public void onFail(String error) {
                TCLoadingDataView.dismiss();
//                ToastUtil.showToast(AppContext.getInstance(), "提现失败");
                showAlertDailog(ResStringUtil.getString(R.string.open_planet_withdraw_fail), false);
                LogUtils.i(error + "");
            }
        });

    }

    /**
     * 设置付款地址信息
     */
    private void setPayData() {
        if (curAccount == null) {
            return;
        }
        tvPay.setText(curAccount.getAddress());
        tvWallet.setText(curAccount.getAcccountName());
    }

    private void dealBalance() {
        if (curAccountBalance < withdrawFee) {
            tvInsufficientBalance.setVisibility(View.VISIBLE);
        } else {
            tvInsufficientBalance.setVisibility(View.GONE);
        }
    }

    /**
     * 切换钱包
     */
    private void showWalletChoose() {

        BottomWalletChooseDialogFragment bottomWalletChooseDialogFragment = new
                BottomWalletChooseDialogFragment();
        bottomWalletChooseDialogFragment.setData(this, walletBeans, ipaChainId);
        bottomWalletChooseDialogFragment.setStyle(STYLE_NO_FRAME, 0);
        bottomWalletChooseDialogFragment.hideBalace(true);
        bottomWalletChooseDialogFragment.show(getSupportFragmentManager(), "WalletChoose");
        bottomWalletChooseDialogFragment.setOnWalletSelectChangedListener(new BottomWalletChooseDialogFragment.OnWalletSelectChangedListener() {
            @Override
            public void onWalletChanged(WalletBean walletBean) {
                curAddress = walletBean.getAddress();
                curAccount = accountDao.getAccount(curAddress);

                tvWallet.setText(walletBean.getAccountName());
                tvPay.setText(walletBean.getAddress());
                setPayData();
                requestAccountBalance();
            }
        });
    }

    /**
     * 请求账户余额
     */
    public void requestAccountBalance() {
        if (assetsBean.getCoinName().equals("PWR") || assetsBean.getCoinName().equals("ETH")) {
            return;
        }
        HashMap<String, String> map = new HashMap<>();
//>chainId    链编号(2是以太坊、4是涡链)
//>accountAddress 账户地址
//>coinAddress 合约地址（不是智能合约不用传）
//>coinDecimals 合约单位进制位数（不是智能合约不用传）

        if (curAccount == null) {
            return;
        }
        map.put("chainId", assetsBean.getBlockchainId());
        if (assetsBean.getCoinAddress() != null && !"".equals(assetsBean.getCoinAddress())) {
            map.put("coinAddress", assetsBean.getCoinAddress());
        }
        map.put("accountAddress", tvPay.getText().toString());
        map.put("coinDecimals", assetsBean.getCoinDecimals() + "");
        TCRequestUtil.getCommonRequest(TAG, "trusteeship/balance", map, new TCRequestUtil.TCRequestCallback() {
            @Override
            public void onSuccess(String response) {
                dismissLoading();
                try {
                    JSONObject jsonObject = JSONObject.fromObject(response);
                    if ("success".equals(jsonObject.optString("result"))) {
                        curAccountBalance = Double.valueOf(jsonObject.optString("chainBalance", "0.00000000"));
                        dealBalance();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    ToastUtils.showShort(R.string.common_text_http_request_fail);
                }
            }

            @Override
            public void onFail(String error) {
                dismissLoading();
                ToastUtils.showShort(R.string.common_text_http_request_fail);
            }
        });

    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.ll_address) {
            //选择钱包
            showWalletChoose();
        } else if (id == R.id.tv_create_wallet) {
            //提现
            if ("".equals(etQuantity.getText().toString())) {
                ToastUtils.showShort(R.string.open_planet_withdraw_number_not_correct);
                return;
            }
            if (assetsBean.getAvailableCoin() < withdrawFee) {
                ToastUtils.showShort(R.string.open_planet_withdraw_balance_insufficient);
                return;
            }
            if (withdrawQuantity <= withdrawFee) {
                ToastUtils.showShort(R.string.open_planet_withdraw_amount_insufficient);
                return;
            }
            if (withdrawQuantity <= 0) {
                ToastUtils.showShort(R.string.open_planet_withdraw_number_not_correct);
                return;
            }
            if (withdrawQuantity > escrowBalance) {
                //提现数量大于托管余额
                ToastUtils.showShort(String.format(ResStringUtil.getString(R.string.open_planet_at_most_withdraw), TCMathUtil.retainAsignDecimals(escrowBalance, 5) + assetsBean.getCoinName()));
                return;
            }
            PassWordAlertDialog dialog = new PassWordAlertDialog(this, new PassWordAlertDialog.OnEnterClick() {
                @Override
                public void passVerifySuccess(String passWord) {
                    sendWithdrawFee();
                }
            });
            dialog.setCanCancle(true);
            dialog.show();
        } else if (id == R.id.tv_all) {
            etQuantity.setText(TCMathUtil.retainAsignDecimals(escrowBalance, 8) + "");
            etQuantity.setSelection(etQuantity.getText().length());
        }
    }

    private void showAlertDailog(String msg, final boolean finish) {
        new AlertDialog.Builder(this)
                .setMessage(msg)
                .setCancelable(true)
                .setPositiveButton(ResStringUtil.getString(R.string.common_text_confirm  ), new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        if (finish) {
                            finish();
                        }
                    }
                }).show();
    }
}
